package com.thoughtservice.jspdoc.utils;

import java.io.File;
import java.io.IOException;
import java.util.Iterator;

import org.apache.commons.lang.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.thoughtservice.jspdoc.DirTree;
import com.thoughtservice.jspdoc.JSPFileList;
import com.thoughtservice.jspdoc.JSPPage;
import com.thoughtservice.jspdoc.RE;
import com.thoughtservice.jspdoc.RESyntaxException;


public class ProcessorUtils {
	
	private static final Logger LOG = LoggerFactory.getLogger(ProcessorUtils.class);
	/**
	 * Find a JSPPage object given the name of the page
	 * @return ca.yourdecor.jspdoc.JSPPage The JSPPage if found, <code>null</code> otherwise
	 * @param link java.lang.String The file name of the JSPPage to find
	 */
	public static JSPPage getPage(String link, JSPFileList fileList) {
		LOG.trace("Entering {}", "getPage");
		if (link == null)
			return null;
			
//		File f = new File(link);
//		JSPPage jsp = new JSPPage(f);
		
		Iterator i = fileList.fileList();
		JSPPage p;
		while (i.hasNext()) {
			p = (JSPPage) i.next();
			if (p.getName().toLowerCase().equals(link.toLowerCase()))
				return p;
		}
		LOG.trace("Exiting {}", "getPage");
		return null;
	}
	
	/**
	 * Converts from a relative link in a JSP page in the hierarchy of 
	 * JSP pages being documented to a link in the JSPDoc documentation 
	 * hierarchy.
	 * 
	 * @param link java.lang.String The link in the JSP page
	 * @param p ca.yourdecor.jspdoc.JSPPage The page that contains the link
	 * @param type int The type of link
	 * @see JSPPage For more info about link types.
	 */
	public static String figureLink(String link, JSPPage p, int type) throws RESyntaxException {
		LOG.trace("Entering {}", "figureLink");
		/*try {
		System.out.println("******************************");
		String par = "e:\\cc\\cc\\index.jsp";
		String child = "..\\index2.jsp";
		File fr = new File(par, child);
		System.out.println(par +  "    " + child);
		System.out.println(fr.toString());
		System.out.println(fr.getAbsolutePath());
		System.out.println(fr.getAbsoluteFile());
		System.out.println(fr.getCanonicalPath());
		System.out.println("******************************");
		} catch (IOException e) {
			System.out.println(e);
		}*/
		// Get just the href attribute
		LOG.debug("link --> {} : type --> {}", link, type);
		RE re = new RE("\"\\S*\"");
		re.match(link);
		String l = re.getParen(0);
		// If l is null then we have a more complex type of link, JSP mixed with HTML, but
		// most of that has already been filtered off, so just get rid of the first part.
		if (l == null) {
			int q = link.indexOf('"');
			l = link.substring(q + 1, link.length());
		} else {
			// Remove quotes of href attribute value
			l = l.substring(1, l.length() - 1);
			re = new RE("/");
			l = re.subst(l, "\\");
		}
		// Remove the HTTP Query string, if present
		if (l.indexOf("?") != -1) {
			l = l.substring(0, l.indexOf("?"));
		}
		LOG.trace("Exiting {}", "figureLink");
		return addConnection(l, p, type); 
	}
	
	public static String addConnection(String l, JSPPage p, int type) throws RESyntaxException {
		LOG.trace("Entering {}", "addConnection");
		LOG.debug("l --> {} type --> {}", l, type);
		
		String tileName = l;
		//Need to handle tiles:insert diffrently. Obtain value from TilesUtils multimap
		LOG.debug(" isJSP {}", l.endsWith(".jsp"));
		LOG.debug("is JSPF {}",l.endsWith(".jspf"));
		if(!l.endsWith(".jsp") && !l.endsWith(".jspf") && (type == 9 || type == 10)){
			l = TilesUtils.getTileDefs(l);
		}
		
		
		String unixFName;
		// If l starts with a / then we're dealing with an absolute link (absolute
		// within the URL space that is (i.e. something like href="/mod1/somefile.jsp")
		try {
			if (l.startsWith("\\") || l.startsWith("/")) {
				LOG.debug("l starts with a / and we're dealing with an absolute link");
				//unixFName = RootSourceDir;
				String rootDir = DirTree.rootSourceDir.replace('\\', '/');
				if (rootDir.endsWith("/")) 
					unixFName = DirTree.rootSourceDir.substring(0, DirTree.rootSourceDir.lastIndexOf('\\'));
				else
					unixFName = rootDir;
				
			// Otherwise we're dealing with some relative link, so handle it normally.
			} else {
				LOG.debug("Otherwise we're dealing with some relative link, so handle it normally.");
				//System.out.println(l); 
				// Split the file path of the current page
				RE re = new RE("\\\\");
				//	String unixFName = re.subst(p.getName(), "/");
				unixFName = p.getName();
				File page = new File(unixFName);
				if (!page.isDirectory()) {
					page = page.getParentFile();
				}
				unixFName = page.toString();
			}
			//System.out.println(unixFName);
	
			// Figure out the filename using the current page as the basis
			// and the link as a relative file name.  This relies on the
			// java.io.File facilities which are probably correct.
		
			File f = new File(unixFName, l);
			LOG.debug("abspath {} ", f.getAbsolutePath());
			//		System.out.println(f.getAbsoluteFile());
			//		System.out.println(f.getCanonicalPath());
			String file = f.getCanonicalPath();
			//System.out.println(file);
			// Make the first letter lowercase if it is a windows driver letter
			RE re = new RE("^.:");
			if (re.match(file) == true) {
				char c = Character.toLowerCase(file.charAt(0));
				file = c + file.substring(1, file.length());
			}

			// Create the link
			LOG.debug("LINK {}", l);
			if(type == JSPPage.TILE_INSERTS || type == JSPPage.TILE_INSERTS_INPAGE){
				//handle differently
				switch(type){
					case JSPPage.TILE_INSERTS:
						p.addTileInserts(tileName, f);
						break;
					case JSPPage.TILE_INSERTS_INPAGE:
						p.addTileInsertsIn(tileName, f);
						break;
				}
			} else {
				p.addConnection(type, file);
			}
			LOG.trace("Exiting {}", "addConnection");
			return file;
			//System.out.println(file);
		} catch (IOException e) {
			LOG.error(ExceptionUtils.getFullStackTrace(e));
			return null;
		} catch (Exception e) {
			LOG.error(ExceptionUtils.getFullStackTrace(e));
			return null;
		}
	}
	
	/**
	 * Converts from a relative link to a form in a JSP page in the hierarchy of 
	 * JSP pages being documented to a link in the JSPDoc documentation 
	 * hierarchy.  A link in a Form is the value of the "action" attribute of the
	 * form.
	 * 
	 * @param link java.lang.String The link to the form in the JSP page
	 * @param p ca.yourdecor.jspdoc.JSPPage The page that contains the link
	 * @param type int The type of link
	 * @see JSPPage For more info about link types.
	 */
	public static String figureForm(String link, JSPPage p, int type) throws RESyntaxException {
		LOG.trace("Entering {}", "figureForm");
		// Get just the action attribute
		RE re = new RE("action=\"\\S*\"");
		re.match(link);
		String l = re.getParen(0);
		// Get just the contents of the quotes of the action attribute
		if (l != null) {
			re = new RE("\"\\S*\"");
			re.match(l);
			l = re.getParen(0);
		}
			
		// If l is null then we have a more complex type of link, JSP mixed with HTML, but
		// most of that has already been filtered off, so just get rid of the first part.
		if (l == null) {
			int q = link.indexOf('"');
			l = link.substring(q + 1, link.length());
		} else {
			// Remove quotes of href attribute value
			l = l.substring(1, l.length() - 1);
			re = new RE("/");
			l = re.subst(l, "\\");
		}
		// Remove the HTTP Query string, if present
		if (l.indexOf("?") != -1) {
			l = l.substring(0, l.indexOf("?"));
		}
		LOG.trace("Exiting {}", "figureForm");
		return ProcessorUtils.addConnection(l, p, type); 
	}
	
	/**
	 * Find the JSPPage objects in the given Vector which have the ExtraData key <code>keyName</code> equal
	 * to the value <code>value</code>.  This is useful for figuring out which JSPs in a directory have this
	 * extra data value set or not.  This is used when printing out the results of the report.	 * 
	 */
	protected boolean pagesWithExtraData(Iterator i, String keyName, Object value) {
		LOG.trace("Entering {}", "pagesWithExtraData");
		while (i.hasNext()) {
			JSPPage p = (JSPPage) i.next();
			File pn = new File(p.getName());
			if ( ! pn.isDirectory() && p.getExtraData(keyName) != null && p.getExtraData(keyName).equals(value)) {
				return true;
			}
		}
		LOG.trace("Exiting {}", "pagesWithExtraData");
		return false;
	}

}
